package xyz.xpman.prisonerfitness.util;

import android.os.Build;

import androidx.annotation.RequiresApi;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * @author 江理_网猿 (timor)
 * @date 2019/11/18 0018
 */
@SuppressWarnings("unused")
@RequiresApi(api = Build.VERSION_CODES.O)
public class EncryptUtil {
    public static final Charset UTF_8 = StandardCharsets.UTF_8;

    public static final String KEY_MD5 = "md5";
    public static final String KEY_SHA = "sha";
    /**
     * MAC算法可选以下多种算法:
     *      HmacMD5
     *      HmacSHA1
     *      HmacSHA256
     *      HmacSHA384
     *      HmacSHA512
     */
    public static final String KEY_MAC = "HmacMD5";

    public static final Base64.Encoder ENCODER =  Base64.getEncoder();
    public static final Base64.Decoder DECODER =  Base64.getDecoder();

    private EncryptUtil() {}


    // byte[] to string
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    public static String toHexString(byte[] byteArray) {
        if (byteArray == null || byteArray.length < 1) {
            return "";
        }

        final StringBuilder result = new StringBuilder();

        for (byte b : byteArray) {
            int i = (0x000000FF & b) | 0xFFFFFF00;
            result.append(Integer.toHexString(i).substring(6));
        }

        return result.toString();
    }

    // base64
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    public static String encryptBase64(String key) {
        return ENCODER.encodeToString(key.getBytes(UTF_8));
    }


    public static byte[] decryptBase64(String key) {
        return DECODER.decode(key);
    }

    public static String encryptBase64(byte[] key) {
        return ENCODER.encodeToString(key);
    }


    // md5
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    /**
     * 生成MD5
     * null + null = nullnull
     * null与String连接时，null会变成"null"与String想连
     * @param str 字符串数据
     * @return MD5
     */
    public static String md5(String str){
        return md5(str, "");
    }

    /**
     * 生成MD5
     * null + null = nullnull
     * null与String连接时，null会变成"null"与String想连
     * @param str 字符串数据
     * @param slat 盐
     * @return MD5
     */
    public static String md5(String str, String slat) {
        String result = "";
        try {
            str = str + slat;
            MessageDigest m = MessageDigest.getInstance(KEY_MD5);
            m.update(str.getBytes(UTF_8));

            result = toHexString(m.digest());
        } catch (NoSuchAlgorithmException ignored) { }

        return result;
    }

    public static byte[] md5(byte[] data) {
        byte[] result = new byte[0];
        try {
            MessageDigest m = MessageDigest.getInstance(KEY_MD5);
            m.update(data);

            result = m.digest();
        } catch (NoSuchAlgorithmException ignored) { }

        return result;
    }


    // sha 加密后为40个字符
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    public static String encryptSha(String data) {
        return toHexString(encryptSha(data.getBytes(UTF_8)));
    }

    public static byte[] encryptSha(byte[] data) {
        byte[] result = new byte[0];

        try {
            MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
            sha.update(data);
            result = sha.digest();
        } catch (NoSuchAlgorithmException ignored) { }

        return result;
    }


    // HMAC
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    public static String getMacKey() {
        String key;
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);
            SecretKey secretKey = keyGenerator.generateKey();
            key = encryptBase64(secretKey.getEncoded());
        } catch (NoSuchAlgorithmException e) {
            key = MyUuidUtil.get();
        }
        return key;
    }

    public static String encryptHmac(String data, String key) {
        return toHexString(encryptHmac(data.getBytes(UTF_8), key));
    }

    public static byte[] encryptHmac(byte[] data, String key) {
        byte[] bytes = new byte[0];
        try {
            SecretKey secretKey = new SecretKeySpec(decryptBase64(key), KEY_MAC);
            Mac mac = Mac.getInstance(secretKey.getAlgorithm());
            mac.init(secretKey);
            bytes = mac.doFinal(data);
        } catch (NoSuchAlgorithmException | InvalidKeyException ignored) { }

        return bytes;
    }



}
